#pragma once
#include "IOUringEventLoop.h"
#include "Thread.h"
#include <atomic>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include <string>

class IOUringEventLoop;
class IOUringEventLoopThread {

  public:
    using NewConnectionCallback =
        std::function<void(IOUringEventLoop *loop, struct io_uring_cqe *cqe)>;
    using WriteCompleteCallback =
        std::function<void(IOUringEventLoop *loop, struct io_uring_cqe *cqe)>;
    using ReadCompleteCallback =
        std::function<void(IOUringEventLoop *loop, struct io_uring_cqe *cqe)>;
    using ThreadInitCallback = std::function<void(IOUringEventLoop *)>;

    IOUringEventLoopThread(int acceptFd,
                           const ThreadInitCallback &cb = ThreadInitCallback(),
                           const std::string &name = std::string());
    ~IOUringEventLoopThread();

    IOUringEventLoop *startLoop();

    void setNewConnectionCallback(NewConnectionCallback cb) {
        newConnectionCallback_ = cb;
    }
    void setWriteCompleteCallback(WriteCompleteCallback cb) {
        writeCompleteCallback_ = cb;
    }
    void setReadCompleteCallback(ReadCompleteCallback cb) {
        readCompleteCallback_ = cb;
    }

  private:
    void threadFunc();

    IOUringEventLoop *loop_;
    bool exiting_;
    Thread thread_;
    int acceptFd_;

    std::mutex mutex_;
    std::condition_variable cond_;
    ThreadInitCallback callback_;

    NewConnectionCallback newConnectionCallback_;
    WriteCompleteCallback writeCompleteCallback_;
    ReadCompleteCallback readCompleteCallback_;

}; // class IOUringEventLoopThread
